import type {
  IPagination,
  IPost,
  IPostClientDetails,
  IPostEditInfo,
  IPostFavourite,
  IPostFollowsMessage,
  IPostNewInfo,
  IPostReviewHistory,
  IPostStatistics,
  IQueryPostDetails,
  IUploadPostContent,
  IUploadPostCover,
  IUploadPostNewFile,
} from '@/interfaces';
import type {
  TBody,
  TParams,
  TPostCompositeState,
  TPostSortState,
} from '@/types';
import { createConfig, getQueryParams, handleReqMiddleware } from '@/lib/api';

export const queryPostRandom = (
  params?: TParams,
): Promise<Response | IPost[]> => {
  const config = createConfig(params);
  return fetch(config.baseURL + '/forum/posts/random', config).then(
    handleReqMiddleware,
  );
};

export const queryPostStatistics = (
  params?: TParams,
): Promise<Response | IPostStatistics> => {
  const config = createConfig(params);
  return fetch(config.baseURL + '/forum/posts/statistics', config).then(
    handleReqMiddleware,
  );
};

export const queryPostNewInfo = (
  params?: TParams,
): Promise<Response | IPostNewInfo> => {
  const config = createConfig(params);
  return fetch(config.baseURL + '/forum/posts/new', config).then(
    handleReqMiddleware,
  );
};

export const queryPostEditInfo = (
  params?: TParams,
): Promise<Response | IPostEditInfo> => {
  const config = createConfig(params);
  return fetch(config.baseURL + `/forum/posts/${config.id}/edit`, config).then(
    handleReqMiddleware,
  );
};

export const queryPostDetails = (
  params?: TParams,
): Promise<Response | IQueryPostDetails> => {
  const config = createConfig(params);
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/details`,
    config,
  ).then(handleReqMiddleware);
};

export const clientQueryPostDetails = (
  params?: TParams,
): Promise<Response | IPostClientDetails> => {
  const config = createConfig(params);
  return fetch(
    config.baseURL +
      `/forum/posts/client/${config.id}/details?${getQueryParams(config)}`,
    config,
  ).then(handleReqMiddleware);
};

export const queryAllPost = (
  params?: TParams,
): Promise<Response | IPagination<IPost>> => {
  const config = createConfig(params);
  return fetch(
    config.baseURL + `/forum/posts?${getQueryParams(config)}`,
    config,
  ).then(handleReqMiddleware);
};

export const clientQueryAllPost = (
  params?: TParams,
): Promise<Response | IPagination<IPost>> => {
  const config = createConfig(params);
  return fetch(
    config.baseURL + `/forum/posts/client?${getQueryParams(config)}`,
    config,
  ).then(handleReqMiddleware);
};

export const queryAllPostReviewHistoryById = (
  params?: TParams,
): Promise<Response | IPostReviewHistory[]> => {
  const config = createConfig(params);
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/reviewHistory`,
    config,
  ).then(handleReqMiddleware);
};

export const updatePostNewInfo = (
  params: TBody<{
    sectionId?: number;
    name?: string;
    cover?: string;
    overview?: string;
    content?: string;
    statement?: string;
    customTags?: string[];
    otherStatus?: string;
    secret?: string;
  }>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'POST' });
  return fetch(config.baseURL + '/forum/posts/new', config).then((value) =>
    handleReqMiddleware(value, true),
  );
};

export const updatePostEditInfo = (
  params: TBody<{
    sectionId?: number;
    name?: string;
    cover?: string;
    overview?: string;
    content?: string;
    statement?: string;
    customTags?: string[];
    otherStatus?: string;
    secret?: string;
  }>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'PUT' });
  return fetch(config.baseURL + `/forum/posts/${config.id}/edit`, config).then(
    handleReqMiddleware,
  );
};

export const updatePostStatus = (
  params: TBody<{
    compositeState?: TPostCompositeState;
    sortState?: TPostSortState;
    secret?: string;
    compositeReason?: string;
    sortReason?: string;
  }>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'PATCH' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/status`,
    config,
  ).then(handleReqMiddleware);
};

export const updatePostTagByName = (
  params: TBody<{
    name: string;
  }>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'PATCH' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/tags/${params.data!.name}`,
    config,
  ).then(handleReqMiddleware);
};

export const removePostTagByName = (
  params: TBody<{
    name: string;
  }>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'DELETE' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/tags/${params.data!.name}`,
    config,
  ).then(handleReqMiddleware);
};

export const uploadPostCover = (
  params: TBody<{
    file?: string | Blob;
    formData?: FormData;
  }>,
): Promise<Response | IUploadPostCover> => {
  const { file, signal } = params.data as any;
  const formData = new FormData();
  formData.append('file', file);

  const config = createConfig(params, {
    method: 'POST',
    body: formData as any,
    signal,
  });
  return fetch(config.baseURL + `/file/posts/${config.id}/cover`, config).then(
    handleReqMiddleware,
  );
};

export const uploadPostContent = (
  params: TBody<{
    file?: string | Blob;
    signal?: AbortSignal;
    onUploadProgress?: (progressEvent: ProgressEvent) => void;
    formData?: FormData;
  }>,
): Promise<Response | IUploadPostContent> => {
  const { file, signal } = params.data as any;
  const formData = new FormData();
  formData.append('file', file);

  const config = createConfig(params, {
    method: 'POST',
    body: formData as any,
    signal,
  });
  return fetch(
    config.baseURL + `/file/posts/${config.id}/content`,
    config,
  ).then(handleReqMiddleware);
};

export const uploadPostNewFile = (
  params: TBody<{
    file?: string | Blob;
    signal?: AbortSignal;
    onUploadProgress?: (progressEvent: ProgressEvent) => void;
    formData?: FormData;
  }>,
): Promise<Response | IUploadPostNewFile> => {
  const { file, signal } = params.data as any;
  const formData = new FormData();
  formData.append('file', file);

  const config = createConfig(params, {
    method: 'POST',
    body: formData as any,
    signal,
  });
  return fetch(config.baseURL + '/file/posts/new', config).then(
    handleReqMiddleware,
  );
};

export const postLike = (params?: TParams): Promise<Response | void> => {
  const config = createConfig(params);
  return fetch(config.baseURL + `/forum/posts/${config.id}/like`, config).then(
    handleReqMiddleware,
  );
};

export const postCancelLike = (
  params: TBody<void>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'DELETE' });
  return fetch(config.baseURL + `/forum/posts/${config.id}/like`, config).then(
    handleReqMiddleware,
  );
};

export const postFollow = (params?: TParams): Promise<Response | void> => {
  const config = createConfig(params);
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/follow`,
    config,
  ).then(handleReqMiddleware);
};

export const postCancelFollow = (
  params: TBody<void>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'DELETE' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/follow`,
    config,
  ).then(handleReqMiddleware);
};

export const postFavourite = (params?: TParams): Promise<Response | void> => {
  const config = createConfig(params);
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/favourite`,
    config,
  ).then(handleReqMiddleware);
};

export const postCancelFavourite = (
  params: TBody<void>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'DELETE' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/favourite`,
    config,
  ).then(handleReqMiddleware);
};

export const removePost = (
  params: TBody<void>,
): Promise<Response | boolean> => {
  const config = createConfig(params, { method: 'DELETE' });
  return fetch(config.baseURL + `/forum/posts/${config.id}`, config).then(
    handleReqMiddleware,
  );
};

export const postView = (params: TBody<void>): Promise<Response | void> => {
  const config = createConfig(params, { method: 'POST' });
  return fetch(config.baseURL + `/forum/posts/${config.id}/view`, config).then(
    handleReqMiddleware,
  );
};

export const queryPostFavourites = (
  params?: TParams,
): Promise<Response | IPostFavourite[]> => {
  const config = createConfig(params);
  return fetch(config.baseURL + '/forum/posts/favourites', config).then(
    handleReqMiddleware,
  );
};

export const queryPostFollowMessage = (
  params?: TParams,
): Promise<Response | IPostFollowsMessage[]> => {
  const config = createConfig(params);
  return fetch(config.baseURL + '/forum/posts/follows/message', config).then(
    handleReqMiddleware,
  );
};

export const postFollowRead = (
  params: TBody<void>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'POST' });
  return fetch(
    config.baseURL + `/forum/posts/follows/${config.id}/read`,
    config,
  ).then(handleReqMiddleware);
};

export const createFollow = (params: TBody<void>): Promise<Response | void> => {
  const config = createConfig(params, { method: 'POST' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/follow/add`,
    config,
  ).then(handleReqMiddleware);
};

export const removeFollow = (params: TBody<void>): Promise<Response | void> => {
  const config = createConfig(params, { method: 'DELETE' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/follow/remove`,
    config,
  ).then(handleReqMiddleware);
};

export const createFavourite = (
  params: TBody<void>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'POST' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/favourite/add`,
    config,
  ).then(handleReqMiddleware);
};

export const removeFavourite = (
  params: TBody<void>,
): Promise<Response | void> => {
  const config = createConfig(params, { method: 'DELETE' });
  return fetch(
    config.baseURL + `/forum/posts/${config.id}/favourite/remove`,
    config,
  ).then(handleReqMiddleware);
};
